#############################################################################
#
# Just Another Package Builder http://code.google.com/p/japb
# (c)2011-13 Alexander Galanin
#
# Functions for Tcl packages and libraries handling
#
# $Id$
#
#############################################################################

package require Tcl 8.5
package require japb::filenode

package provide japb::tcl 1.0

namespace eval japb {

namespace export tcl

namespace eval tcl {

namespace import ::japb::filenode

if {[info exists tcl_pkgPath]} {
    variable corelibPath [concat $::tcl_library $::tcl_pkgPath]
} else {
    variable corelibPath $::tcl_library
}
# append more library paths on windows
if {$::tcl_platform(platform) eq "windows"} {
    lappend corelibPath \
        [file normalize [file join [file dirname [info nameofexe]] .. lib]]
} else {
    lappend corelibPath /usr/lib /usr/share/tcltk
}

variable tcllibPath {}
variable tklibPath {}

namespace import [namespace parent]::registerOption
namespace import [namespace parent]::registerPostParseCommand

registerOption -libpath tcl::corelibPath "Tcl library path"
registerOption -tcllibpath tcl::tcllibPath "Tcllib path"
registerOption -tklibpath tcl::tklibPath "Tklib path"

registerPostParseCommand [namespace code normalizePaths]
registerPostParseCommand [namespace code autoDetectTcllibTklibPath]

# Normalize directory paths
proc normalizePaths {} {
    foreach var {corelibPath tcllibPath tklibPath} {
        variable $var
        set $var [file normalize [set $var]]
    }
}

# Auto-detect paths for tcllib and tklib if corresponding variables are empty
proc autoDetectTcllibTklibPath {} {
    variable corelibPath
    variable tcllibPath
    variable tklibPath

    if {$tcllibPath eq ""} {
        foreach path $corelibPath {
            lappend tcllibPath \
                {*}[glob -nocomplain -path $path/ tcllib\[0-9\]*]
        }
    }
    if {$tklibPath eq ""} {
        foreach path $corelibPath {
            lappend tklibPath \
                {*}[glob -nocomplain -path $path/ tklib\[0-9\]*]
        }
    }
}

# Make Tcl package index file by scanning all .tcl files in directory for
# 'package provide' commands.
# @param path path to analyze
proc makeTclIndex {path} {
    file delete -force [file join $path pkgIndex.tcl]
    set f [open [file join $path pkgIndex.tcl] w]
    foreach pkg [glob -tails -nocomplain -path $path/ *.tcl] {
        if {[string tolower $pkg] eq "pkgindex.tcl"} {
            continue
        }
        set fullname [file join $path $pkg]

        set ff [open $fullname r]
        set data {}
        while {[gets $ff line] >= 0} {
            lappend data $line
        }
        set data [join $data \n]
        close $ff

        if {[regexp -lineanchor {^package provide ([^\s]+) ([^\s]+)} $data _ name ver]} {
            puts $f [subst -nocommands {package ifneeded $name $ver [list source [file join \$dir $pkg]]}]
        }
    }
    close $f
}

# Search for libraries (in directories or .tcl files) in the specified paths
# and return file nodes for founded libraries. Each file node is placed into
# 'lib' subdir by default.
# @param paths paths to search in
# @param args library names
# @return list of file nodes for founded libraries
proc lib {paths args} {
    set res {}
    foreach file $args {
        set fi {}
        foreach dir $paths {
            set n [file join $dir $file]
            if {[file exists $n]} {
                set fi [filenode create $n lib/$file]
                break
            }
            if {[file exists $n.tcl]} {
                set fi [filenode create $n.tcl lib/$file.tcl]
                break
            }
        }
        if {$fi eq ""} {
            error "`$file' package not found in search path: $paths"
        }
        lappend res $fi
    }
    return $res
}

# Search for library in Tcl library and package path
# @param args library names
proc corelib {args} {
    variable corelibPath
    lib $corelibPath {*}$args
}

# Search for library in Tcllib
# @param args library names
proc tcllib {args} {
    variable tcllibPath
    lib $tcllibPath {*}$args
}

# Search for library in Tklib
# @param args library names
proc tklib {args} {
    variable tklibPath
    lib $tklibPath {*}$args
}

namespace export \
    makeTclIndex \
    lib \
    corelib \
    tcllib \
    tklib
namespace ensemble create
}

}

